<!--

    Copyright © 2016-2024 The Thingsboard Authors

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

-->
<mat-tab-group class="tab-group-block" [formGroup]="basicFormGroup" [class.dialog-mode]="dialogMode">
  <mat-tab label="{{ 'gateway.general' | translate }}">
    <ng-template matTabContent>
      <div formGroupName="thingsboard" class="mat-content mat-padding configuration-block">
        <div class="tb-form-panel no-padding-bottom">
          <div tb-hint-tooltip-icon="{{ 'gateway.hints.remote-configuration' | translate }}"
               class="tb-form-row no-border no-padding">
            <mat-slide-toggle class="mat-slide" color="primary" formControlName="remoteConfiguration">
              {{ 'gateway.remote-configuration'  | translate }}
            </mat-slide-toggle>
          </div>
          <div tb-hint-tooltip-icon="{{ 'gateway.hints.remote-shell' | translate }}"
               class="tb-form-row no-border no-padding">
            <mat-slide-toggle class="mat-slide" color="primary" formControlName="remoteShell">
              {{ 'gateway.remote-shell' | translate }}
            </mat-slide-toggle>
          </div>
          <div class="tb-form-row no-border no-padding tb-standard-fields">
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.thingsboard-host</mat-label>
              <input matInput formControlName="host"/>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.host' | translate }}">info_outlined
              </mat-icon>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.host').hasError('required')">
                {{ 'gateway.thingsboard-host-required' | translate }}
              </mat-error>
            </mat-form-field>
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.thingsboard-port</mat-label>
              <input matInput formControlName="port" type="number" min="0"/>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.port').hasError('required')">
                {{ 'gateway.thingsboard-port-required' | translate }}
              </mat-error>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.port').hasError('min')">
                {{ 'gateway.thingsboard-port-min' | translate }}
              </mat-error>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.port').hasError('max')">
                {{ 'gateway.thingsboard-port-max' | translate }}
              </mat-error>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.port').hasError('pattern')">
                {{ 'gateway.thingsboard-port-pattern' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.port' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
          </div>
        </div>
        <div class="tb-form-panel">
          <div translate class="tb-form-panel-title">security.security</div>
          <ng-container formGroupName="security">
            <tb-toggle-select class="toggle-group" formControlName="type">
              <tb-toggle-option *ngFor="let securityType of securityTypes | keyvalue"
                                [value]="securityType.key">{{ securityType.value | translate }}
              </tb-toggle-option>
            </tb-toggle-select>
            <mat-form-field appearance="outline"
                            *ngIf="basicFormGroup.get('thingsboard.security.type').value.toLowerCase().includes('accesstoken')">
              <mat-label translate>security.access-token</mat-label>
              <input matInput formControlName="accessToken"/>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.security.accessToken').hasError('required')">
                {{ 'security.access-token-required' | translate }}
              </mat-error>
              <tb-copy-button
                matSuffix
                miniButton="false"
                *ngIf="basicFormGroup.get('thingsboard.security.accessToken').value"
                [copyText]="basicFormGroup.get('thingsboard.security.accessToken').value"
                tooltipText="{{ 'device.copy-access-token' | translate }}"
                tooltipPosition="above"
                icon="content_copy">
              </tb-copy-button>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.token' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
            <section>
              <div class="tb-form-row no-border no-padding tb-standard-fields"
                   *ngIf="basicFormGroup.get('thingsboard.security.type').value === 'usernamePassword'">
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>security.clientId</mat-label>
                  <input matInput formControlName="clientId"/>
                  <mat-error *ngIf="basicFormGroup.get('thingsboard.security.clientId').hasError('required')">
                    {{ 'security.clientId-required' | translate }}
                  </mat-error>
                  <tb-copy-button
                    matSuffix
                    miniButton="false"
                    *ngIf="basicFormGroup.get('thingsboard.security.clientId').value"
                    [copyText]="basicFormGroup.get('thingsboard.security.clientId').value"
                    tooltipText="{{ 'gateway.copy-client-id' | translate }}"
                    tooltipPosition="above"
                    icon="content_copy">
                  </tb-copy-button>
                  <mat-icon matIconSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.client-id' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>security.username</mat-label>
                  <input matInput formControlName="username"/>
                  <mat-error *ngIf="basicFormGroup.get('thingsboard.security.username').hasError('required')">
                    {{ 'security.username-required' | translate }}
                  </mat-error>
                  <tb-copy-button
                    matSuffix
                    miniButton="false"
                    *ngIf="basicFormGroup.get('thingsboard.security.username').value"
                    [copyText]="basicFormGroup.get('thingsboard.security.username').value"
                    tooltipText="{{ 'gateway.copy-username' | translate }}"
                    tooltipPosition="above"
                    icon="content_copy">
                  </tb-copy-button>
                  <mat-icon matIconSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.username' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
              </div>
              <mat-form-field appearance="outline" subscriptSizing="dynamic" style="width: 100%"
                              *ngIf="basicFormGroup.get('thingsboard.security.type').value === 'usernamePassword'">
                <mat-label translate>gateway.password</mat-label>
                <input matInput formControlName="password"/>
                <tb-copy-button
                  matSuffix
                  miniButton="false"
                  *ngIf="basicFormGroup.get('thingsboard.security.password').value"
                  [copyText]="basicFormGroup.get('thingsboard.security.password').value"
                  tooltipText="{{ 'gateway.copy-password' | translate }}"
                  tooltipPosition="above"
                  icon="content_copy">
                </tb-copy-button>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.password' | translate }}">info_outlined
                </mat-icon>
              </mat-form-field>
            </section>
            <tb-error style="margin-top: -12px; display: block;" fxFlex="100"
                      *ngIf="basicFormGroup.get('thingsboard.security.type').value === 'usernamePassword'"
                      [error]="basicFormGroup.get('thingsboard.security').hasError('atLeastOne') ?
          ('device.client-id-or-user-name-necessary' | translate) : ''"></tb-error>
            <tb-file-input
              fxFlex="100"
              hint="{{ 'gateway.hints.ca-cert' | translate }}"
              *ngIf="basicFormGroup.get('thingsboard.security.type').value.toLowerCase().includes('tls')"
              formControlName="caCert"
              label="{{ 'security.ca-cert' | translate }}"
              [allowedExtensions]="'pem, cert, key'"
              [accept]="'.pem, application/pem,.cert, application/cert, .key,application/key'"
              dropLabel="{{ 'gateway.drop-file' | translate }}">
            </tb-file-input>
          </ng-container>
        </div>
      </div>
    </ng-template>
  </mat-tab>
  <mat-tab label="{{ 'gateway.logs.logs' | translate }}">
    <ng-template matTabContent>
      <div formGroupName="logs" class="mat-content mat-padding configuration-block">
        <div class="tb-form-panel no-padding-bottom">
          <div fxLayout="column">
            <mat-form-field appearance="outline">
              <mat-label translate>gateway.logs.date-format</mat-label>
              <input matInput formControlName="dateFormat"/>
              <mat-error *ngIf="basicFormGroup.get('logs.dateFormat').hasError('required')">
                {{ 'gateway.logs.date-format-required' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.date-form' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
            <mat-form-field appearance="outline">
              <mat-label translate>gateway.logs.log-format</mat-label>
              <textarea matInput formControlName="logFormat" rows="2"></textarea>
              <mat-error *ngIf="basicFormGroup.get('logs.logFormat').hasError('required')">
                {{ 'gateway.logs.log-format-required' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.log-format' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
          </div>
        </div>
        <div class="tb-form-panel no-padding-bottom" formGroupName="remote">
          <div translate class="tb-form-panel-title">gateway.logs.remote</div>
          <div tb-hint-tooltip-icon="{{ 'gateway.hints.remote-log' | translate }}"
               class="tb-form-row no-border no-padding">
            <mat-slide-toggle class="mat-slide" color="primary" formControlName="enabled">
              {{ 'gateway.logs.remote-logs'  | translate }}
            </mat-slide-toggle>
          </div>
          <mat-form-field appearance="outline">
            <mat-label translate>gateway.logs.level</mat-label>
            <mat-select formControlName="logLevel">
              <mat-option *ngFor="let logLevel of gatewayLogLevel" [value]="logLevel">{{ logLevel }}</mat-option>
            </mat-select>
          </mat-form-field>
        </div>
        <div class="tb-form-panel no-padding-bottom" formGroupName="local">
          <div translate class="tb-form-panel-title">gateway.logs.local</div>
          <tb-toggle-select class="toggle-group" [formControl]="logSelector">
            <tb-toggle-option *ngFor="let logConfig of localLogsConfigs" [value]="logConfig"
                              class="first-capital">{{ localLogsConfigTranslateMap.get(logConfig) }}</tb-toggle-option>
          </tb-toggle-select>
          <ng-container [formGroup]="getLogFormGroup(logSelector.value)">
            <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.logs.level</mat-label>
                <mat-select formControlName="logLevel">
                  <mat-option *ngFor="let logLevel of gatewayLogLevel" [value]="logLevel">{{ logLevel }}</mat-option>
                </mat-select>
              </mat-form-field>
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.logs.file-path</mat-label>
                <input matInput formControlName="filePath"/>
                <mat-error *ngIf="basicFormGroup.get('logs.local.' + logSelector.value + '.filePath').hasError('required')">
                  {{ 'gateway.logs.file-path-required' | translate }}
                </mat-error>
              </mat-form-field>
            </div>
            <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">
              <div class="tb-form-row no-border no-padding tb-standard-fields saving-period">
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>gateway.logs.saving-period</mat-label>
                  <input matInput formControlName="savingTime" type="number" min="0"/>
                  <mat-error
                    *ngIf="basicFormGroup.get('logs.local.' + logSelector.value + '.savingTime').hasError('required')">
                    {{ 'gateway.logs.saving-period-required' | translate }}
                  </mat-error>
                  <mat-error
                    *ngIf="basicFormGroup.get('logs.local.' + logSelector.value + '.savingTime').hasError('min')">
                    {{ 'gateway.logs.saving-period-min' | translate }}
                  </mat-error>
                </mat-form-field>
                <mat-form-field appearance="outline" hideRequiredMarker style="min-width: 110px; width: 30%">
                  <mat-select formControlName="savingPeriod">
                    <mat-option *ngFor="let period of logSavingPeriods | keyvalue" [value]="period.key">
                      {{ period.value | translate }}
                    </mat-option>
                  </mat-select>
                </mat-form-field>
              </div>
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.logs.backup-count</mat-label>
                <input matInput formControlName="backupCount" type="number" min="0"/>
                <mat-error
                  *ngIf="basicFormGroup.get('logs.local.' + logSelector.value + '.backupCount').hasError('required')">
                  {{ 'gateway.logs.backup-count-required' | translate }}
                </mat-error>
                <mat-error
                  *ngIf="basicFormGroup.get('logs.local.' + logSelector.value + '.backupCount').hasError('min')">
                  {{ 'gateway.logs.backup-count-min' | translate }}
                </mat-error>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.backup-count' | translate }}">info_outlined
                </mat-icon>
              </mat-form-field>
            </div>
          </ng-container>
        </div>
      </div>
    </ng-template>
  </mat-tab>
  <mat-tab label="{{ 'gateway.storage' | translate }}">
    <ng-template matTabContent>
      <div formGroupName="storage" class="mat-content mat-padding configuration-block">
        <div class="tb-form-panel no-padding-bottom">
          <div translate class="tb-form-panel-title">gateway.storage</div>
          <div translate class="tb-form-panel-hint">gateway.hints.storage</div>
          <tb-toggle-select class="toggle-group" formControlName="type">
            <tb-toggle-option *ngFor="let storageType of storageTypes" [value]="storageType">
              {{ storageTypesTranslationMap.get(storageType) | translate }}
            </tb-toggle-option>
          </tb-toggle-select>
          <div class="tb-form-panel-hint">{{ 'gateway.hints.' + basicFormGroup.get('storage.type').value | translate }}</div>
          <ng-container [ngSwitch]="basicFormGroup.get('storage.type').value">
            <section *ngSwitchCase="StorageTypes.MEMORY" class="tb-form-row no-border no-padding tb-standard-fields column-xs">
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.storage-read-record-count</mat-label>
                <input type="number" matInput formControlName="read_records_count"/>
                <mat-error *ngIf="basicFormGroup.get('storage.read_records_count').hasError('required')">
                  {{ 'gateway.storage-read-record-count-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('storage.read_records_count').hasError('min')">
                  {{ 'gateway.storage-read-record-count-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('storage.read_records_count').hasError('pattern')">
                  {{ 'gateway.storage-read-record-count-pattern' | translate }}
                </mat-error>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.read-record-count' | translate }}">info_outlined
                </mat-icon>
              </mat-form-field>
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.storage-max-records</mat-label>
                <input type="number" matInput formControlName="max_records_count"/>
                <mat-error *ngIf="basicFormGroup.get('storage.max_records_count').hasError('required')">
                  {{ 'gateway.storage-max-records-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('storage.max_records_count').hasError('min')">
                  {{ 'gateway.storage-max-records-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('storage.max_records_count').hasError('pattern')">
                  {{ 'gateway.storage-max-records-pattern' | translate }}
                </mat-error>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.max-records-count' | translate }}">info_outlined
                </mat-icon>
              </mat-form-field>
            </section>
            <section *ngSwitchCase="StorageTypes.FILE">
              <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>gateway.storage-data-folder-path</mat-label>
                  <input matInput formControlName="data_folder_path"/>
                  <mat-error *ngIf="basicFormGroup.get('storage.data_folder_path').hasError('required')">
                    {{ 'gateway.storage-data-folder-path-required' | translate }}
                  </mat-error>
                  <mat-icon class="mat-form-field-infix pointer-event suffix-icon" aria-hidden="false"
                            aria-label="help-icon"
                            matSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.data-folder' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>gateway.storage-max-files</mat-label>
                  <input matInput type="number" formControlName="max_file_count"/>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_file_count').hasError('required')">
                    {{ 'gateway.storage-max-files-required' | translate }}
                  </mat-error>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_file_count').hasError('min')">
                    {{ 'gateway.storage-max-files-min' | translate }}
                  </mat-error>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_file_count').hasError('pattern')">
                    {{ 'gateway.storage-max-files-pattern' | translate }}
                  </mat-error>
                  <mat-icon matIconSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.max-file-count' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
              </div>
              <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>gateway.storage-max-read-record-count</mat-label>
                  <input matInput type="number" formControlName="max_read_records_count"/>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_read_records_count').hasError('required')">
                    {{ 'gateway.storage-max-read-record-count-required' | translate }}
                  </mat-error>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_read_records_count').hasError('min')">
                    {{ 'gateway.storage-max-read-record-count-min' | translate }}
                  </mat-error>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_read_records_count').hasError('pattern')">
                    {{ 'gateway.storage-max-read-record-count-pattern' | translate }}
                  </mat-error>
                  <mat-icon matIconSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.max-read-count' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>gateway.storage-max-file-records</mat-label>
                  <input matInput type="number" formControlName="max_records_per_file"/>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_records_per_file').hasError('required')">
                    {{ 'gateway.storage-max-records-required' | translate }}
                  </mat-error>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_records_per_file').hasError('min')">
                    {{ 'gateway.storage-max-records-min' | translate }}
                  </mat-error>
                  <mat-error *ngIf="basicFormGroup.get('storage.max_records_per_file').hasError('pattern')">
                    {{ 'gateway.storage-max-records-pattern' | translate }}
                  </mat-error>
                  <mat-icon matIconSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.max-records' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
              </div>
            </section>
            <section *ngSwitchCase="StorageTypes.SQLITE">
              <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>gateway.storage-path</mat-label>
                  <input matInput formControlName="data_file_path"/>
                  <mat-error *ngIf="basicFormGroup.get('storage.data_file_path').hasError('required')">
                    {{ 'gateway.storage-path-required' | translate }}
                  </mat-error>
                  <mat-icon matIconSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.data-folder' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
                <mat-form-field appearance="outline" class="flex">
                  <mat-label translate>gateway.messages-ttl-check-in-hours</mat-label>
                  <input matInput type="number" formControlName="messages_ttl_check_in_hours"/>
                  <mat-error *ngIf="basicFormGroup.get('storage.messages_ttl_check_in_hours').hasError('required')">
                    {{ 'gateway.messages-ttl-check-in-hours-required' | translate }}
                  </mat-error>
                  <mat-error *ngIf="basicFormGroup.get('storage.messages_ttl_check_in_hours').hasError('min')">
                    {{ 'gateway.messages-ttl-check-in-hours-min' | translate }}
                  </mat-error>
                  <mat-error *ngIf="basicFormGroup.get('storage.messages_ttl_check_in_hours').hasError('pattern')">
                    {{ 'gateway.messages-ttl-check-in-hours-pattern' | translate }}
                  </mat-error>
                  <mat-icon matIconSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.ttl-check-hour' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
              </div>
              <mat-form-field appearance="outline" class="mat-block">
                <mat-label translate>gateway.messages-ttl-in-days</mat-label>
                <input matInput type="number" formControlName="messages_ttl_in_days"/>
                <mat-error *ngIf="basicFormGroup.get('storage.messages_ttl_in_days').hasError('required')">
                  {{ 'gateway.messages-ttl-in-days-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('storage.messages_ttl_in_days').hasError('min')">
                  {{ 'gateway.messages-ttl-in-days-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('storage.messages_ttl_in_days').hasError('pattern')">
                  {{ 'gateway.messages-ttl-in-days-pattern' | translate }}
                </mat-error>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.ttl-messages-day' | translate }}">info_outlined
                </mat-icon>
              </mat-form-field>
            </section>
          </ng-container>
        </div>
      </div>
    </ng-template>
  </mat-tab>
  <mat-tab label="{{ 'gateway.grpc' | translate }}">
    <ng-template matTabContent>
      <div formGroupName="grpc" class="mat-content mat-padding configuration-block">
        <div class="tb-form-panel no-padding-bottom">
          <mat-slide-toggle class="mat-slide" color="primary" formControlName="enabled">
            {{ 'gateway.grpc'  | translate }}
          </mat-slide-toggle>
          <div tb-hint-tooltip-icon="{{ 'gateway.hints.permit-without-calls' | translate }}"
               class="tb-form-row no-border no-padding">
            <mat-slide-toggle class="mat-slide" color="primary" formControlName="keepalivePermitWithoutCalls">
              {{ 'gateway.permit-without-calls'  | translate }}
            </mat-slide-toggle>
          </div>
          <section>
            <section class="tb-form-row no-border no-padding tb-standard-fields column-xs">
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.server-port</mat-label>
                <input matInput formControlName="serverPort" type="number" min="0"/>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.server-port' | translate }}">info_outlined
                </mat-icon>
                <mat-error *ngIf="basicFormGroup.get('grpc.serverPort').hasError('required')">
                  {{ 'gateway.thingsboard-port-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.serverPort').hasError('min')">
                  {{ 'gateway.thingsboard-port-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.serverPort').hasError('max')">
                  {{ 'gateway.thingsboard-port-max' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.serverPort').hasError('pattern')">
                  {{ 'gateway.thingsboard-port-pattern' | translate }}
                </mat-error>
              </mat-form-field>
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.grpc-keep-alive-timeout</mat-label>
                <input matInput formControlName="keepAliveTimeoutMs" type="number" min="0"/>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.grpc-keep-alive-timeout' | translate }}">info_outlined
                </mat-icon>
                <mat-error *ngIf="basicFormGroup.get('grpc.keepAliveTimeoutMs').hasError('required')">
                  {{ 'gateway.grpc-keep-alive-timeout-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.keepAliveTimeoutMs').hasError('min')">
                  {{ 'gateway.grpc-keep-alive-timeout-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.keepAliveTimeoutMs').hasError('pattern')">
                  {{ 'gateway.grpc-keep-alive-timeout-pattern' | translate }}
                </mat-error>
              </mat-form-field>
            </section>
            <section class="tb-form-row no-border no-padding tb-standard-fields column-xs">
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.grpc-keep-alive</mat-label>
                <input matInput formControlName="keepAliveTimeMs" type="number" min="0"/>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.grpc-keep-alive' | translate }}">info_outlined
                </mat-icon>
                <mat-error *ngIf="basicFormGroup.get('grpc.keepAliveTimeMs').hasError('required')">
                  {{ 'gateway.grpc-keep-alive-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.keepAliveTimeMs').hasError('min')">
                  {{ 'gateway.grpc-keep-alive-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.keepAliveTimeMs').hasError('pattern')">
                  {{ 'gateway.grpc-keep-alive-pattern' | translate }}
                </mat-error>
              </mat-form-field>
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.grpc-min-time-between-pings</mat-label>
                <input matInput formControlName="minTimeBetweenPingsMs" type="number" min="0"/>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.grpc-min-time-between-pings' | translate }}">info_outlined
                </mat-icon>
                <mat-error *ngIf="basicFormGroup.get('grpc.minTimeBetweenPingsMs').hasError('required')">
                  {{ 'gateway.grpc-min-time-between-pings-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.minTimeBetweenPingsMs').hasError('min')">
                  {{ 'gateway.grpc-min-time-between-pings-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.minTimeBetweenPingsMs').hasError('pattern')">
                  {{ 'gateway.grpc-min-time-between-pings-pattern' | translate }}
                </mat-error>
              </mat-form-field>
            </section>
            <section class="tb-form-row no-border no-padding tb-standard-fields column-xs">
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.grpc-max-pings-without-data</mat-label>
                <input matInput formControlName="maxPingsWithoutData" type="number" min="0"/>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.grpc-max-pings-without-data' | translate }}">info_outlined
                </mat-icon>
                <mat-error *ngIf="basicFormGroup.get('grpc.maxPingsWithoutData').hasError('required')">
                  {{ 'gateway.grpc-max-pings-without-data-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.maxPingsWithoutData').hasError('min')">
                  {{ 'gateway.grpc-max-pings-without-data-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.maxPingsWithoutData').hasError('pattern')">
                  {{ 'gateway.grpc-max-pings-without-data-pattern' | translate }}
                </mat-error>
              </mat-form-field>
              <mat-form-field appearance="outline" class="flex">
                <mat-label translate>gateway.grpc-min-ping-interval-without-data</mat-label>
                <input matInput formControlName="minPingIntervalWithoutDataMs" type="number" min="0"/>
                <mat-icon matIconSuffix style="cursor:pointer;"
                          matTooltip="{{ 'gateway.hints.grpc-min-ping-interval-without-data' | translate }}">info_outlined
                </mat-icon>
                <mat-error *ngIf="basicFormGroup.get('grpc.minPingIntervalWithoutDataMs').hasError('required')">
                  {{ 'gateway.grpc-min-ping-interval-without-data-required' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.minPingIntervalWithoutDataMs').hasError('min')">
                  {{ 'gateway.grpc-min-ping-interval-without-data-min' | translate }}
                </mat-error>
                <mat-error *ngIf="basicFormGroup.get('grpc.minPingIntervalWithoutDataMs').hasError('pattern')">
                  {{ 'gateway.grpc-min-ping-interval-without-data-pattern' | translate }}
                </mat-error>
              </mat-form-field>
            </section>
          </section>
        </div>
      </div>
    </ng-template>
  </mat-tab>
  <mat-tab label="{{ 'gateway.statistics.statistics' | translate }}">
    <ng-template matTabContent>
      <div formGroupName="thingsboard" class="mat-content mat-padding configuration-block">
        <div class="tb-form-panel no-padding-bottom" formGroupName="statistics">
          <mat-slide-toggle color="primary" class="mat-slide" formControlName="enable">
            {{ 'gateway.statistics.statistics'  | translate }}
          </mat-slide-toggle>
          <mat-form-field appearance="outline">
            <mat-label translate>gateway.statistics.send-period</mat-label>
            <input matInput formControlName="statsSendPeriodInSeconds" type="number" min="60"/>
            <mat-error
              *ngIf="basicFormGroup.get('thingsboard.statistics.statsSendPeriodInSeconds').hasError('required')">
              {{ 'gateway.statistics.send-period-required' | translate }}
            </mat-error>
            <mat-error
              *ngIf="basicFormGroup.get('thingsboard.statistics.statsSendPeriodInSeconds').hasError('min')">
              {{ 'gateway.statistics.send-period-min' | translate }}
            </mat-error>
            <mat-error
              *ngIf="basicFormGroup.get('thingsboard.statistics.statsSendPeriodInSeconds').hasError('pattern')">
              {{ 'gateway.statistics.send-period-pattern' | translate }}
            </mat-error>
          </mat-form-field>
        </div>
        <div class="tb-form-panel">
          <div class="tb-form-panel-title" translate>gateway.statistics.commands</div>
          <div class="tb-form-panel-hint" translate>gateway.hints.commands</div>
          <ng-container formGroupName="statistics">
            <div fxLayout="row" formArrayName="commands" class="statistics-container"
                 *ngFor="let commandControl of commandFormArray().controls; let $index = index">
              <section [formGroupName]="$index" class="tb-form-panel stroked no-padding-bottom no-gap command-container">
                <section class="tb-form-row no-border no-padding tb-standard-fields column-xs">
                  <mat-form-field appearance="outline" class="flex">
                    <mat-label translate>gateway.statistics.attribute-name</mat-label>
                    <input matInput formControlName="attributeOnGateway"/>
                    <mat-error *ngIf="commandControl.get('attributeOnGateway').hasError('required')">
                      {{ 'gateway.statistics.attribute-name-required' | translate }}
                    </mat-error>
                    <mat-icon matIconSuffix style="cursor:pointer;"
                              matTooltip="{{ 'gateway.hints.attribute' | translate }}">info_outlined
                    </mat-icon>
                  </mat-form-field>
                  <mat-form-field appearance="outline" class="flex">
                    <mat-label translate>gateway.statistics.timeout</mat-label>
                    <input matInput formControlName="timeout" type="number" min="0"/>
                    <mat-error *ngIf="commandControl.get('timeout').hasError('required')">
                      {{ 'gateway.statistics.timeout-required' | translate }}
                    </mat-error>
                    <mat-error *ngIf="commandControl.get('timeout').hasError('min')">
                      {{ 'gateway.statistics.timeout-min' | translate }}
                    </mat-error>
                    <mat-error *ngIf="commandControl.get('timeout').hasError('pattern')">
                      {{ 'gateway.statistics.timeout-pattern' | translate }}
                    </mat-error>
                    <mat-icon matIconSuffix style="cursor:pointer;"
                              matTooltip="{{ 'gateway.hints.timeout' | translate }}">info_outlined
                    </mat-icon>
                  </mat-form-field>
                </section>
                <mat-form-field appearance="outline" class="mat-block">
                  <mat-label translate>gateway.statistics.command</mat-label>
                  <input matInput formControlName="command"/>
                  <mat-error *ngIf="commandControl.get('command').hasError('required')">
                    {{ 'gateway.statistics.command-required' | translate }}
                  </mat-error>
                  <mat-error *ngIf="commandControl.get('command').hasError('pattern')">
                    {{ 'gateway.statistics.command-pattern' | translate }}
                  </mat-error>
                  <mat-icon matIconSuffix style="cursor:pointer;"
                            matTooltip="{{ 'gateway.hints.command' | translate }}">info_outlined
                  </mat-icon>
                </mat-form-field>
              </section>
              <button mat-icon-button (click)="removeCommandControl($index, $event)"
                      class="tb-box-button"
                      [disabled]="!basicFormGroup.get('thingsboard.remoteConfiguration').value"
                      matTooltip="{{ 'gateway.statistics.remove' | translate }}"
                      matTooltipPosition="above">
                <mat-icon>delete</mat-icon>
              </button>
            </div>
            <button mat-stroked-button color="primary"
                    style="width: fit-content;"
                    type="button"
                    [disabled]="!basicFormGroup.get('thingsboard.remoteConfiguration').value"
                    (click)="addCommand()">
              {{ 'gateway.statistics.add' | translate }}
            </button>
          </ng-container>
        </div>
      </div>
    </ng-template>
  </mat-tab>
  <mat-tab label="{{ 'gateway.other' | translate }}">
    <ng-template matTabContent>
      <div formGroupName="thingsboard" class="mat-content mat-padding configuration-block">
        <div class="tb-form-panel" formGroupName="checkingDeviceActivity"
             [class.no-padding-bottom]="basicFormGroup.get('thingsboard.checkingDeviceActivity.checkDeviceInactivity').value">
          <div tb-hint-tooltip-icon="{{ 'gateway.hints.check-device-activity' | translate }}"
               class="tb-form-row no-border no-padding">
            <mat-slide-toggle class="mat-slide" color="primary" formControlName="checkDeviceInactivity">
              {{ 'gateway.checking-device-activity'  | translate }}
            </mat-slide-toggle>
          </div>
          <section class="tb-form-row no-border no-padding tb-standard-fields column-xs"
                   *ngIf="basicFormGroup.get('thingsboard.checkingDeviceActivity.checkDeviceInactivity').value">
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.inactivity-timeout-seconds</mat-label>
              <input matInput formControlName="inactivityTimeoutSeconds" type="number" min="0"/>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkingDeviceActivity.inactivityTimeoutSeconds').hasError('required')">
                {{ 'gateway.inactivity-timeout-seconds-required' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkingDeviceActivity.inactivityTimeoutSeconds').hasError('min')">
                {{ 'gateway.inactivity-timeout-seconds-min' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkingDeviceActivity.inactivityTimeoutSeconds').hasError('pattern')">
                {{ 'gateway.inactivity-timeout-seconds-pattern' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.inactivity-timeout' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.inactivity-check-period-seconds</mat-label>
              <input matInput formControlName="inactivityCheckPeriodSeconds"/>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkingDeviceActivity.inactivityCheckPeriodSeconds').hasError('required')">
                {{ 'gateway.inactivity-check-period-seconds-required' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkingDeviceActivity.inactivityCheckPeriodSeconds').hasError('min')">
                {{ 'gateway.inactivity-check-period-seconds-min' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkingDeviceActivity.inactivityCheckPeriodSeconds').hasError('pattern')">
                {{ 'gateway.inactivity-check-period-seconds-pattern' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.inactivity-period' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
          </section>
        </div>
        <div class="tb-form-panel no-padding-bottom">
          <div class="tb-form-panel-title" translate>gateway.advanced</div>
          <section class="tb-form-row no-border no-padding tb-standard-fields column-xs">
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.min-pack-send-delay</mat-label>
              <input matInput formControlName="minPackSendDelayMS" type="number" min="0"/>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.minPackSendDelayMS').hasError('required')">
                {{ 'gateway.min-pack-send-delay-required' | translate }}
              </mat-error>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.minPackSendDelayMS').hasError('min')">
                {{ 'gateway.min-pack-send-delay-min' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.minPackSendDelayMS').hasError('pattern')">
                {{ 'gateway.min-pack-send-delay-pattern' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.minimal-pack-delay' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.mqtt-qos</mat-label>
              <input matInput formControlName="qos" type="number" min="0" max="1"/>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.qos').hasError('required')">
                {{ 'gateway.mqtt-qos-required' | translate }}
              </mat-error>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.qos').hasError('min')">
                {{ 'gateway.mqtt-qos-range' | translate }}
              </mat-error>
              <mat-error *ngIf="basicFormGroup.get('thingsboard.qos').hasError('max')">
                {{ 'gateway.mqtt-qos-range' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.qos' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
          </section>
          <section class="tb-form-row no-border no-padding tb-standard-fields column-xs">
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.statistics.check-connectors-configuration</mat-label>
              <input matInput formControlName="checkConnectorsConfigurationInSeconds" type="number" min="0"/>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkConnectorsConfigurationInSeconds').hasError('required')">
                {{ 'gateway.statistics.check-connectors-configuration-required' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkConnectorsConfigurationInSeconds').hasError('min')">
                {{ 'gateway.statistics.check-connectors-configuration-min' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.checkConnectorsConfigurationInSeconds').hasError('pattern')">
                {{ 'gateway.statistics.check-connectors-configuration-pattern' | translate }}
              </mat-error>
            </mat-form-field>
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.statistics.max-payload-size-bytes</mat-label>
              <input matInput formControlName="maxPayloadSizeBytes" type="number" min="0"/>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.maxPayloadSizeBytes').hasError('required')">
                {{ 'gateway.statistics.max-payload-size-bytes-required' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.maxPayloadSizeBytes').hasError('min')">
                {{ 'gateway.statistics.max-payload-size-bytes-min' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.maxPayloadSizeBytes').hasError('pattern')">
                {{ 'gateway.statistics.max-payload-size-bytes-pattern' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.max-payload-size-bytes' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
          </section>
          <section class="tb-form-row no-border no-padding tb-standard-fields column-xs">
            <mat-form-field appearance="outline" class="flex">
              <mat-label translate>gateway.statistics.min-pack-size-to-send</mat-label>
              <input matInput formControlName="minPackSizeToSend" type="number" min="0"/>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.minPackSizeToSend').hasError('required')">
                {{ 'gateway.statistics.min-pack-size-to-send-required' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.minPackSizeToSend').hasError('min')">
                {{ 'gateway.statistics.min-pack-size-to-send-min' | translate }}
              </mat-error>
              <mat-error
                *ngIf="basicFormGroup.get('thingsboard.minPackSizeToSend').hasError('pattern')">
                {{ 'gateway.statistics.min-pack-size-to-send-pattern' | translate }}
              </mat-error>
              <mat-icon matIconSuffix style="cursor:pointer;"
                        matTooltip="{{ 'gateway.hints.min-pack-size-to-send' | translate }}">info_outlined
              </mat-icon>
            </mat-form-field>
          </section>
        </div>
      </div>
    </ng-template>
  </mat-tab>
</mat-tab-group>
